# 类与面向对象

class Person:
    '所有员工的基类'    # 对类的说明
    personCount = 0 # 静态变量

    # 构造函数：新建对象时被自动调用
    def __init__(self, name, sex, age):
        self.id = Person.personCount    # 人的编号
        self.name = name                # 人的姓名
        self.sex = sex                  # 人的性别
        self.age = age                  # 人的年龄
        self.__id_add()                 # 每创建一个新的对象，编号自增1
        print("名为" + self.name + "的人类对象被创建了")
    # 析构函数：销毁对象时被自动调用
    def __del__(self):
        print("名为" + self.name + "的人类对象被销毁了")

    def compareClassAndInstance(self):
        print (self)
        print(self.__class__)

    def tostring(self):
        return "id:" + str(self.id) + " name:" + str(self.name) + " sex:" + str(self.sex) + " age:" + str(self.age)
    
    # 以"_"命名的为受保护对象protected
    # 给予人类一种行为：吃饭
    def _eat(self):
        print("名为" + self.name + "的人类对象开始吃饭...")

    # 以"__"命名的为私有成员private
    def __id_add(self):
        Person.personCount += 1

class Student(Person):
    '人类的子类：学生'
    def __init__(self, name, sex, age):
        # 显式调用父类构造函数
        super().__init__(name, sex, age)
        print("名为" + self.name + "的学生对象被创建了")
    def __del__(self):
        super().__del__()
        print("名为" + self.name + "的学生对象被销毁了")
    
    # 学生继承了人类的吃饭行为，并可以在此基础上重写逻辑
    def _eat(self):
        super()._eat()
    # 学生也可以有自己的行为：学习
    def _study(self):
        print("名为" + self.name + "的学生对象开始学习...")

# main
# 创建一个属于Person类的对象person1
# 创建对象的时候默认调用类的构造函数__init__
person1 = Person("zhangsan", True, 18)
# 创建一个属于Person类的对象person2
person2 = Person("lisi", False, 18)
person1.compareClassAndInstance()             

# 访问对象的静态成员变量
print(Person.personCount)
# 访问对象的实例成员变量
print(person1.name)
print(person1.tostring())   
# 修改person1对象的年龄为22
person1.age = 22; print(person1.tostring())
print(Person.__doc__, Person.__name__, Person.__bases__)

# 垃圾回收
person3 = Person("wangwu", True, 26) # person3指向新建的对象
person4 = person3                    # person4同样指向person3所指的对象
del person3                          # 销毁person3，但person4仍指向原对象，故没有销毁对象
del person4                          # 销毁person4，此时已经没有指针指向对象，对象被回收(调用__del__函数)
# while (True) : pass                  # 程序执行结束会自动垃圾回收，此处阻塞程序，不让其结束

# 学生子类
student1 = Student("李华", True, 24) # 自动执行学生类的__init__函数
setattr(student1, "age", 22)        # 修改学生对象1的年龄为22岁
print(student1.tostring())          # 调用子对象的父类函数
student1._eat()                      # 学生1调用父类的吃饭函数
student1._study()                    # 学生1调用自己的学习函数